package com.itheima.app.manager;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.StrUtil;
import com.github.tobato.fastdfs.domain.conn.FdfsWebServer;
import com.github.tobato.fastdfs.domain.fdfs.StorePath;
import com.github.tobato.fastdfs.service.FastFileStorageClient;
import com.itheima.app.interceptor.UserHolder;
import com.itheima.domain.db.UserInfo;
import com.itheima.domain.mongo.Comment;
import com.itheima.domain.mongo.FocusUser;
import com.itheima.domain.mongo.Video;
import com.itheima.service.db.UserInfoService;
import com.itheima.service.mongo.CommentService;
import com.itheima.service.mongo.FocusUserService;
import com.itheima.service.mongo.VideoService;
import com.itheima.util.ConstantUtil;
import com.itheima.vo.CommentVo;
import com.itheima.vo.PageBeanVo;
import com.itheima.vo.VideoVo;
import org.apache.dubbo.config.annotation.DubboReference;
import org.bson.types.ObjectId;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

@Component
public class VideoManager {

    @DubboReference
    private VideoService videoService;

    @DubboReference
    private UserInfoService userInfoService;

    @Autowired
    private VideoMQManager videoMQManager;

    /*
           99_1_10
           99_2_10

           2_1_10
           2_2_10
     */
    // 推荐视频查询
    @Cacheable(value = "tanhua", key = "#userId+'_'+#pageNum+'_'+#pageSize")
    public PageBeanVo findRecommendVideoVoByPage(Long userId, Integer pageNum, Integer pageSize) {
        System.out.println("查询数据库....");
        // 1.调用rpc查询推荐视频
        PageBeanVo pageBeanVo = videoService.findRecommendVideoByPage(userId, pageNum, pageSize);
        // 2.封装vo
        // 2-1 声明voList
        List<VideoVo> voList = new ArrayList<>();
        // 2-2 获取videoList
        List<Video> videoList = (List<Video>) pageBeanVo.getItems();
        // 2-3 遍历videoList
        if (CollectionUtil.isNotEmpty(videoList)) {
            for (Video video : videoList) {
                // 查询userInfo
                UserInfo userInfo = userInfoService.findByUserId(video.getUserId());
                // 创建vo
                VideoVo vo = new VideoVo();
                vo.setUserInfo(userInfo); // 先
                vo.setVideo(video); // 后

                // 判断我是否关注了对方
                if (stringRedisTemplate.hasKey(StrUtil.format(ConstantUtil.FOCUS_USER, userId, video.getUserId()))) {
                    vo.setHasFocus(1);
                }
                if (stringRedisTemplate.hasKey((StrUtil.format(ConstantUtil.VIDEO_LIKE, userId, video.getId())))) {
                    System.out.println((StrUtil.format(ConstantUtil.VIDEO_LIKE, userId, video.getId())));
                    vo.setHasLiked(1);
                }
                // 添加集合
                voList.add(vo);
            }
        }

        // 3.voList设置到分页对象
        pageBeanVo.setItems(voList);

        // 4.返回分页对象
        return pageBeanVo;
    }

    @Autowired
    private FastFileStorageClient client;

    @Autowired
    private FdfsWebServer webServer;

    // 发布视频
    // @CacheEvict(value = "tanhua",allEntries = true)
    @CacheEvict(value = "tanhua", key = "#userId+'_*'")
    public void publishVideo(Long userId, MultipartFile videoThumbnail, MultipartFile videoFile) throws Exception {
        // 1.封装上传fastDFS
        StorePath storePath1 = client.uploadFile(videoThumbnail.getInputStream(), videoThumbnail.getSize(), FileUtil.extName(videoThumbnail.getOriginalFilename()), null);
        String picUrl = webServer.getWebServerUrl() + storePath1.getFullPath();
        // 2.视频上传fastDFS
        StorePath storePath2 = client.uploadFile(videoFile.getInputStream(), videoFile.getSize(), FileUtil.extName(videoFile.getOriginalFilename()), null);
        String videoUrl = webServer.getWebServerUrl() + storePath2.getFullPath();
        // 3.封装video
        Video video = new Video();
        video.setId(ObjectId.get()); // 视频id
        video.setCreated(System.currentTimeMillis()); // 发布时间
        video.setUserId(userId);// 发布人
        video.setPicUrl(picUrl);// 封面
        video.setVideoUrl(videoUrl);// 视频
        // 4.调用rpc保存
        videoService.publishVideo(video);
        //5.发送mq消息
        videoMQManager.sendMovement(userId, video.getId(), VideoMQManager.MOVEMENT_PUBLISH);
    }

    @DubboReference
    private FocusUserService focusUserService;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @DubboReference
    private CommentService commentService;

    // 关注
    public void userFocus(Long userId, Long focusUserId) {
        // 1.封装实体
        FocusUser focusUser = new FocusUser();
        focusUser.setCreated(System.currentTimeMillis());// 关注时间
        focusUser.setUserId(userId); // 登录人id
        focusUser.setFocusUserId(focusUserId);// 视频发布人id
        // 2.调用rpc保存
        focusUserService.save(focusUser);
        // 3.redis存储关注标记   focus_user:{userId}_{focusUserId}
        stringRedisTemplate.opsForValue().set(StrUtil.format(ConstantUtil.FOCUS_USER, userId, focusUserId), "1");
    }

    // 取消关注
    public void userUnFocus(Long userId, Long focusUserId) {
        // 1.调用rpc删除
        focusUserService.remove(userId, focusUserId);
        // 2.redis删除关注标记
        stringRedisTemplate.delete(StrUtil.format(ConstantUtil.FOCUS_USER, userId, focusUserId));
    }

    // 视频点赞
    @CacheEvict(value = "tanhua", key = "#userId+'_*'")
    public ResponseEntity videoLike(Long userId, String videoId) {
        // 2.查询动态详情
        Video video = videoService.findById(new ObjectId(videoId));
        // 3.封装comment
        Comment comment = new Comment();
        comment.setCreated(System.currentTimeMillis()); // 点赞时间
        comment.setPublishId(new ObjectId(videoId)); // 动态id
        comment.setUserId(userId); // 操作人id
        comment.setCommentType(4); // 类型-点赞
        comment.setPublishUserId(video.getUserId()); // 动态发布人id
        // 4.调用rpc保存
        Integer likeCount = commentService.saveComment(comment);

        // 5.向redis存储点赞标记    :  movement_like:{userId}_{publishId} = 4
        stringRedisTemplate.opsForValue().set(StrUtil.format(ConstantUtil.VIDEO_LIKE, userId, videoId), "4");

        //6.发送mq消息（推荐）
        videoMQManager.sendMovement(userId, new ObjectId(videoId), VideoMQManager.MOVEMENT_LIKE);

        // 6.返回数量
        return ResponseEntity.ok(likeCount);

    }

    // 视频点赞 - 取消
    @CacheEvict(value = "tanhua", key = "#userId+'_*'")
    public ResponseEntity videoDislike(Long userId, String videoId) {
        // 2.调用rpc删除
        Integer likeCount = commentService.removeComment(userId, new ObjectId(videoId), 4);
        // 3.从redis中删除点赞标记
        stringRedisTemplate.delete(StrUtil.format(ConstantUtil.VIDEO_LIKE, userId, videoId));
        //发送mq消息
        videoMQManager.sendMovement(userId, new ObjectId(videoId), VideoMQManager.MOVEMENT_DISLIKE);

        // 4.返回数量
        return ResponseEntity.ok(likeCount);
    }

    //评论列表
    public ResponseEntity findVideoCommentsByPage(String videoId, Integer pageNum, Integer pageSize) {
        // 获取线程内userId
        Long userId = UserHolder.get().getId();
        PageBeanVo pageBeanVo = commentService.findCommentByPage(new ObjectId(videoId), 5, pageNum, pageSize);
        //声明
        ArrayList<CommentVo> commentVoList = new ArrayList<>();
        //获取
        List<Comment> comments = (List<Comment>) pageBeanVo.getItems();
        //判断遍历
        if (CollectionUtil.isNotEmpty(comments)) {
            for (Comment comment : comments) {
                UserInfo userInfo = userInfoService.findByUserId(comment.getUserId());
                CommentVo commentVo = new CommentVo();
                commentVo.setId(comment.getId().toHexString());
                commentVo.setAvatar(userInfo.getAvatar());
                commentVo.setNickname(userInfo.getNickname());
                commentVo.setContent(comment.getContent());
                commentVo.setCreateDate(DateUtil.formatDate(new Date(comment.getCreated())));
                commentVo.setLikeCount(comment.getLikeCount());
                if (stringRedisTemplate.hasKey(StrUtil.format(ConstantUtil.VIDEO_COMMENT_LIKE, userId, comment.getId()))) {
                    commentVo.setHasLiked(1);
                }
                commentVoList.add(commentVo);
            }
            pageBeanVo.setItems(commentVoList);

        }
        //返回
        return ResponseEntity.ok(pageBeanVo);

    }

    // 评论发布
    public void saveVideosComments(String videoId, String comment) {
        // 获取线程内userId
        Video video = videoService.findById(new ObjectId(videoId));
        Long userId = UserHolder.get().getId();
        Comment comment2 = new Comment();
        comment2.setCreated(System.currentTimeMillis());
        comment2.setPublishId(new ObjectId(videoId));
        comment2.setCommentType(5);
        comment2.setUserId(userId);
        comment2.setPublishUserId(video.getUserId());
        comment2.setContent(comment);
        commentService.saveComment(comment2);
        //发送mq消息
        videoMQManager.sendMovement(userId, new ObjectId(videoId), VideoMQManager.MOVEMENT_COMMENT);

    }

    //评论点赞
    public ResponseEntity videosCommentLike(String videosCommentLikeId) {
        Comment commentById = commentService.findById(new ObjectId(videosCommentLikeId));
        // 获取线程内userId
        Long userId = UserHolder.get().getId();
        Comment comment = new Comment();
        comment.setCreated(System.currentTimeMillis());
        comment.setPublishId(new ObjectId(videosCommentLikeId));
        comment.setCommentType(6);
        comment.setUserId(userId);
        comment.setPublishUserId(comment.getUserId());//被操作对象所属人

        Integer commentLikeCount = commentService.saveComment(comment);
        // 5. 向redis中存储点赞标记   movement_love:{userId}_{publishId} = 1
        stringRedisTemplate.opsForValue().set(StrUtil.format(ConstantUtil.VIDEO_COMMENT_LIKE, userId, commentById.getId()), "6");
        //返回
        return ResponseEntity.ok(commentLikeCount);

    }

    //评论点赞 - 取消
    public ResponseEntity videosCommentDislike(String videosCommentLikeId) {
        // 1.获取线程内userId
        Long userId = UserHolder.get().getId();
        // 2.根据三个条件调用rpc删除
        Integer commentLikeCount = commentService.removeComment(userId, new ObjectId(videosCommentLikeId), 6);
        // 3.从redis中删除点赞标记
        stringRedisTemplate.delete(StrUtil.format(ConstantUtil.VIDEO_COMMENT_LIKE, userId, videosCommentLikeId));
        //返回
        return ResponseEntity.ok(commentLikeCount);
    }
}
